﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media.Media3D;
using System.Windows;
using System.Windows.Media;
using Eniux.Windows.ThreeDEngine.Helper;
using Eniux.Windows.ThreeDEngine.AttachObject;

namespace Eniux.Windows.ThreeDEngine.Visual3Ds
{
    /// <summary>
    /// 派生类应重写 Tessellate()方法生成几何模型,该几何模型，接受鼠标事件
    /// </summary>
    public abstract class HitMeshElement3D : ModelVisual3DExtend
    {
        public override ModelUIElement3D HitElement3D { get; set; }

        #region 注册依赖属性

        #region Material（材质）
        /// <summary>
        /// 获取或设置材质属性
        /// </summary>
        public Material Material
        {
            get { return (Material)GetValue(MaterialProperty); }
            set { SetValue(MaterialProperty, value); }
        }
        /// <summary>
        /// 材质属性
        /// </summary>
        public static readonly DependencyProperty MaterialProperty = DependencyProperty.Register(
            "Material",
            typeof(Material),
            typeof(HitMeshElement3D),
            new UIPropertyMetadata(MaterialHelper.CreateMaterial(Brushes.Gray), MaterialChanged));
        #endregion

        #region BackMaterial（背面材质）
        /// <summary>
        /// 获取或设置背面材质
        /// </summary>
        public Material BackMaterial
        {
            get { return (Material)GetValue(BackMaterialProperty); }
            set { SetValue(BackMaterialProperty, value); }
        }
        /// <summary>
        /// 背面材质属性
        /// </summary>
        public static readonly DependencyProperty BackMaterialProperty = DependencyProperty.Register(
            "BackMaterial", typeof(Material), typeof(HitMeshElement3D), new UIPropertyMetadata(null, MaterialChanged));
        #endregion

        #region Fill（填充）
        /// <summary>
        /// 获取或设置填充
        /// </summary>
        public Brush Fill
        {
            get { return (Brush)GetValue(FillProperty); }
            set { SetValue(FillProperty, value); }
        }
        /// <summary>
        /// 填充属性
        /// </summary>
        public static readonly DependencyProperty FillProperty = DependencyProperty.Register(
            "Fill", typeof(Brush), typeof(HitMeshElement3D), new UIPropertyMetadata(null, FillChanged));

        private static void FillChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var el = (MeshElement3D)d;
            el.Material = MaterialHelper.CreateMaterial(el.Fill);
            el.BackMaterial = el.Material;
        }

        #endregion

        #endregion

        #region 构造、析构

        /// <summary>
        /// 默认构造函数
        /// </summary>
        protected HitMeshElement3D()
        {
            GeometryModel3D mode = new GeometryModel3D();
            HitElement3D = new ModelUIElement3D();
            HitElement3D.Model = mode;
            Children.Add(HitElement3D);

            UpdateModel();
        }
        #endregion

        #region 公共属性

        /// <summary>
        /// 获取当前Geometry Model
        /// </summary>
        public GeometryModel3D Model
        {
            get { return (GeometryModel3D)(Children[0] as ModelUIElement3D).Model; }
        }

        #endregion

        #region 公共方法

        /// <summary>
        /// 更新几何模型和材质
        /// </summary>
        public void UpdateModel()
        {
            GeometryChanged();
            MaterialChanged();
        }

        #endregion

        #region 方法

        protected static void GeometryChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((HitMeshElement3D)d).GeometryChanged();
        }

        /// <summary>
        /// 几何模型改变
        /// </summary>
        protected void GeometryChanged()
        {
            Model.Geometry = Tessellate();
        }

        protected static void MaterialChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((HitMeshElement3D)d).MaterialChanged();
        }

        /// <summary>
        /// 材质改变
        /// </summary>
        protected void MaterialChanged()
        {
            Model.Material = Material;
            Model.BackMaterial = BackMaterial;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected abstract MeshGeometry3D Tessellate();


        #endregion
    }
}
